#pragma once
#include <zGraphicsConfig.hpp>
#include "Texture2D.hpp"
#include <ImageIO\ILImage.hpp>

namespace zzz {
template<>
class IOObject<Texture2D>
{
public:
  static void WriteFileB(FILE *fp, const Texture2D &src) {
    IOObj::WriteFileB(fp, src.GetInternalFormat());
    IOObj::WriteFileB(fp, src.GetFilterParam());
    IOObj::WriteFileB(fp, src.GetWrapParam());
    switch(src.GetInternalFormat()) {
    case GL_RGB: {
        Image3uc img;
        src.TextureToImage(img);
        IOObject<Image3uc>::WriteFileB(fp, img);
        break;
    }
    case GL_RGBA: {
        Image4uc img;
        src.TextureToImage(img);
        IOObj::WriteFileB(fp, img);
        break;
    }
    default:
      ZLOGE<<"IOObject<Texture2D>::WriteFileB is not defined for internal format "<<src.GetInternalFormat();
      break;
    }
  }
  static void ReadFileB(FILE *fp, Texture2D& dst) {
    zint32 iformat, fparam, wparam;    
    IOObj::ReadFileB(fp, iformat);
    dst.Create(iformat);
    IOObj::ReadFileB(fp, fparam);
    IOObj::ReadFileB(fp, wparam);
    dst.ChangeParameter(fparam, wparam);
    switch(iformat) {
    case GL_RGB: {
        Image3uc img;
        IOObject<Image3uc>::ReadFileB(fp, img);
        dst.ImageToTexture(img);
        break;
    }
    case GL_RGBA: {
        Image4uc img;
        IOObject<Image4uc>::ReadFileB(fp, img);
        dst.ImageToTexture(img);
        break;
    }
    default:
      ZLOGE<<"IOObject<Texture2D>::ReadFileB is not defined for internal format "<<dst.GetInternalFormat();
      break;
    }
  }
  static const zint32 RF_IFORMAT=1;
  static const zint32 RF_FPARAM=2;
  static const zint32 RF_WPARAM=3;
  static const zint32 RF_IMG=4;
  static void WriteFileR(RecordFile &fp, const zint32 label, const Texture2D& src) {
    fp.WriteChildBegin(label);
    IOObj::WriteFileR(fp, RF_IFORMAT, src.GetInternalFormat());
    IOObj::WriteFileR(fp, RF_FPARAM, src.GetFilterParam());
    IOObj::WriteFileR(fp, RF_WPARAM, src.GetWrapParam());
    switch(src.GetInternalFormat()) {
    case GL_RGB: {
      Image3uc img;
      src.TextureToImage(img);
      IOObj::WriteFileR(fp, RF_IMG, img);
      break;
    }
    case GL_RGBA: {
      Image4uc img;
      src.TextureToImage(img);
      IOObj::WriteFileR(fp, RF_IMG, img);
      break;
    }
    default:
      ZLOGE<<"IOObject<Texture2D>::WriteFileR is not defined for internal format "<<src.GetInternalFormat();
      break;
    }
    fp.WriteChildEnd();
  }
  static void ReadFileR(RecordFile &fp, const zint32 label, Texture2D& dst) {
    fp.ReadChildBegin(label);
    int iformat, fparam, wparam;    
    IOObj::ReadFileR(fp, RF_IFORMAT, iformat);
    dst.Create(iformat);
    IOObj::ReadFileR(fp, RF_FPARAM, fparam);
    IOObj::ReadFileR(fp, RF_WPARAM, wparam);
    dst.ChangeParameter(fparam, wparam);
    switch(iformat) {
    case GL_RGB: {
      Image3uc img;
      IOObj::ReadFileR(fp, RF_IMG, img);
//      ILImage image;  // Add this line to avoid crash for unknown reason, it actually does nothing
      dst.ImageToTexture(img);
      break;
    }
    case GL_RGBA: {
      Image4uc img;
      IOObj::ReadFileR(fp, RF_IMG, img);
      dst.ImageToTexture(img);
      break;
    }
    default:
      ZLOGE<<"IOObject<Texture2D>::ReadFileR is not defined for internal format "<<dst.GetInternalFormat();
      break;
    }
    fp.ReadChildEnd();
  }
};

};  // namespace zzz